前面已經有提到indexedDB是一個在browser運行的Database,這裡我列出幾項主要的特性:
不過在我的project中,為了避免使用callback function,我使用了第三方的套件(由jakearchibald提供),這讓我能使用promise來去操作indexedDB。(記得將code複製到project中js目錄下,並加入到pre-cache中)
IndexedDB Browser Support (96%的瀏覽器都支援,其實算相當不錯的)
接下來我就要將用戶的貼文資料(dynamic data)從原本暫存在cache,移植到indexedDB中囉!!
首先要在sw.js中,導入indexedDB的第三方套件。同時為了之後寫的程式碼能重複利用,我將針對indexedDB的操作寫在utility.js中,所以也需要導入:
importScripts('/src/js/idb.js');
importScripts('/src/js/utility.js');
來看一下在utility.js中要怎麼建立indexedDB的object store並將資料寫入:
var dbPromise = idb.open('post-store', 1, function(db) {
if(!db.objectStoreNames.contains('posts')) {
db.createObjectStore('posts', {keyPath: 'id'});
}
});
function writeData(objectStore, data) {
return dbPromise.then(function(db) {
var tx = db.transaction(objectStore, 'readwrite'); // first step
var store = tx.objectStore(objectStore); // second step
store.put(data); // third step
return tx.complete;
});
}
透過第三方套件,我可以使用idb.open()來建立一個資料庫,需要輸入3個參數(1. 資料庫名稱、2. 資料庫版本[可以隨喜好設定,但不能相同]、3. callback function)。而這個callback function會以建立好的indexedDB object作為輸入,來去操作這個資料庫。
所以在callback function中,我在post-store資料庫中新增一個「名為posts的object store」,而且第二個參數是要去設定在這個object store中,我們要以哪個欄位做為key值。
接著寫要怎麼將firebase的貼文資訊寫入indexedDB呢?事實上操作indexedDB有一個標準執行流程:
可以看到這三個步驟就是上面writeData() function中的3 step
最後在sw.js中,將從firebase裡fetch回來的資料改成儲存到indexedDB:
// Cache then Network
self.addEventListener('fetch', function(event) {
var url = 'https://trip-diary-f56de.firebaseio.com/posts.json';
// 要修改的地方
if(event.request.url.indexOf(url) > -1) {
event.respondWith(
fetch(event.request).then(function(res) {
var clonedRes = res.clone();
clonedRes.json().then(function(data) {
for(var key in data) {
writeData('posts', data[key]);
}
});
return res;
})
);
} else if(isInArray(event.request.url, STATIC_FILES)) {
event.respondWith(
caches.match(event.request)
);
} else {
event.respondWith(
caches.match(event.request).then(function(response) {
if(response) {
return response;
} else {
return fetch(event.request).then(function(res) {
return caches.open(CACHE_DYNAMIC_NAME).then(function(cache) {
// trimCache(CACHE_DYNAMIC_NAME, 20);
cache.put(event.request.url, res.clone());
return res;
})
}).catch(function(err) {
return caches.open(CACHE_STATIC_NAME).then(function(cache) {
if(event.request.headers.get('accept').includes('text/html')) {
return cache.match('/offline.html');
}
});
});
}
})
);
}
});
說明一下,這裡我把firebase fetch回來的response,複製(clone)完後將資料轉成javascript object型式。接著用一個for loop把posts裡面的每一則貼文寫入到"posts" object store中。
來看一下畫面執行的結果吧:
發現我們已經成功地將firebase回傳dynamic data儲存至indexedDB中了,它的key就是我們當初設定的id欄位,value就是貼文的json object。
Day15 結束!!